#include <gtest/gtest.h>
#include <fstream>
#include <thread>
#include <chrono>
#include <filesystem>

#include "base_log.h"
#include "base_init.h"
#include "common_init.h"
#include "nlohmann/json.hpp"
#include "common_product_definition.h"

namespace El {
namespace Common {

class ProductDefinitionTest : public ::testing::Test {
protected:
    static void SetUpTestSuite()
    {
        // 初始化基础库
        nlohmann::json config;
        config["log_file"] = "app.log";
        El::Base::base_init(config);

        // 初始化配置
        config.clear();
        config["general"] = "app_config";
        config["default"] = "default_config";
        El::Common::common_init(config);
    }

    void SetUp() override 
    {
        // 创建临时测试文件
        CreateTestFile();
    }

    void TearDown() override 
    {
        // 清理临时测试文件
        std::filesystem::remove(test_file_);
    }

protected:
    void CreateTestFile()
    {
        test_file_ = "test_product_def.txt";
        std::ofstream file(test_file_);
        file << "product_name=TestCamera\n";
        file << "product_model=TC-100\n";
        file << "hardware_version=1.0.0\n";
        file << "software_version=2.0.0\n";
        file << "max_resolution=1920x1080\n";
        file.close();
    }

    std::string test_file_;
};

// 测试加载配置文件
TEST_F(ProductDefinitionTest, LoadFromFile)
{
    auto &product = ProductDefinition::GetInstance();
    
    // 测试加载有效文件
    EXPECT_TRUE(product.LoadFromFile(test_file_)) << "Failed to load valid product definition file";
    
    // 测试加载不存在的文件
    EXPECT_FALSE(product.LoadFromFile("non_existent_file.txt")) << "Should fail when loading non-existent file";
    
    // 测试加载空文件
    std::ofstream empty_file("empty.txt");
    empty_file.close();
    EXPECT_TRUE(product.LoadFromFile("empty.txt")) << "Should handle empty file gracefully";
    std::filesystem::remove("empty.txt");
}

// 测试获取配置值
TEST_F(ProductDefinitionTest, GetValue)
{
    auto &product = ProductDefinition::GetInstance();
    ASSERT_TRUE(product.LoadFromFile(test_file_));
    
    // 测试获取存在的配置项
    EXPECT_EQ(product.GetValue("product_name"), "TestCamera");
    EXPECT_EQ(product.GetValue("product_model"), "TC-100");
    EXPECT_EQ(product.GetValue("hardware_version"), "1.0.0");
    
    // 测试获取不存在的配置项
    EXPECT_TRUE(product.GetValue("non_existent_key").empty()) << "Should return empty string for non-existent key";
}

// 测试设置配置值
TEST_F(ProductDefinitionTest, SetValue)
{
    auto &product = ProductDefinition::GetInstance();
    
    // 测试设置新的配置项
    product.SetValue("new_key", "new_value");
    EXPECT_EQ(product.GetValue("new_key"), "new_value");
    
    // 测试更新已存在的配置项
    product.SetValue("new_key", "updated_value");
    EXPECT_EQ(product.GetValue("new_key"), "updated_value");
    
    // 测试设置空值
    product.SetValue("empty_key", "");
    EXPECT_TRUE(product.GetValue("empty_key").empty());
}

// 测试并发访问
TEST_F(ProductDefinitionTest, ConcurrentAccess)
{
    auto &product = ProductDefinition::GetInstance();
    ASSERT_TRUE(product.LoadFromFile(test_file_));
    
    std::vector<std::thread> threads;
    const int thread_count = 10;
    
    // 创建多个线程同时读写配置
    for (int i = 0; i < thread_count; ++i) {
        threads.emplace_back([&product, i]() {
            // 写操作
            product.SetValue("key_" + std::to_string(i), "value_" + std::to_string(i));
            // 读操作
            std::string value = product.GetValue("product_name");
            EXPECT_FALSE(value.empty());
        });
    }
    
    // 等待所有线程完成
    for (auto &thread : threads) {
        thread.join();
    }
    
    // 验证所有写入的值
    for (int i = 0; i < thread_count; ++i) {
        EXPECT_EQ(product.GetValue("key_" + std::to_string(i)), "value_" + std::to_string(i));
    }
}

// 测试特殊字符处理
TEST_F(ProductDefinitionTest, SpecialCharacters)
{
    auto &product = ProductDefinition::GetInstance();
    
    // 测试包含特殊字符的键值对
    std::vector<std::pair<std::string, std::string>> special_cases = {
        {"key with spaces", "value with spaces"},
        {"key=with=equals", "value=with=equals"},
        {"empty_value", ""},
        {"unicode_key_测试", "unicode_value_测试"},
        {"key\nwith\nnewlines", "value\nwith\nnewlines"},
        {"key#with#comment", "value#with#comment"}
    };
    
    for (const auto &[key, value] : special_cases) {
        product.SetValue(key, value);
        EXPECT_EQ(product.GetValue(key), value) 
            << "Failed to handle special characters in key: " << key;
    }
}

} // namespace Common
} // namespace El